package com.ideal.hadoopadmin.security;

import com.ideal.hadoopadmin.entity.main.Menu;
import com.ideal.hadoopadmin.entity.main.User;
import com.ideal.hadoopadmin.service.main.SystemMenuService;
import com.ideal.hadoopadmin.service.main.SystemUserService;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by CC on 2016/2/16.
 */
public class ShiroDbRealm extends AuthorizingRealm {

    private static final Logger logger = LoggerFactory.getLogger(ShiroDbRealm.class);

    @Resource
    SystemUserService systemUserService;

    @Resource
    SystemMenuService systemMenuService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
//        User user = systemUserService.getUserByUserName(shiroUser.getLoginName());
        //获取用户的roles
        List<Long> roles = systemUserService.getUserRoles(shiroUser.getId());
        List<Menu> menus= systemMenuService.getMenuByRoles(roles);
        List<String> buttonCode=new ArrayList<String>();
        for(Menu menu:menus){
            //这里过滤出button
            if(menu.getIsParent()!=Menu.ParentMenu&&menu.getType()==Menu.ButtonType){
                buttonCode.add(menu.getCode());
            }
        }
        if(buttonCode.size()>0){
            info.addStringPermissions(buttonCode);
        }

        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String loginName = token.getUsername();
        String passWord = String.valueOf(token.getPassword());
        String decodePassWord= DigestUtils.md5Hex(passWord);
        //认证用户
        User loginUser= null;
        try {
            loginUser = systemUserService.authenticateLoginUser(loginName, decodePassWord);
        } catch (Exception e) {
            System.out.println(e);
        }
//        User loginUser=new User();
        logger.debug("[" + loginName + "]登陆系统！");
        if(loginName!=null){

            //将User放入session中 --start-- by xbb
            Subject currentUser = SecurityUtils.getSubject();
            Session session = currentUser.getSession();
            session.setAttribute("user", loginUser);
            //--end--

            logger.debug("[" + loginName + "]登录成功！");
            return new SimpleAuthenticationInfo(new ShiroUser(loginUser.getId(),
                    loginUser.getUserName(), loginUser.getUserName()),
                    passWord, getName());
        }  else {
            logger.debug("[" + loginName + "]登录失败！");
            return null;
        }
    }


    public static class ShiroUser implements Serializable {
        private Long id;
        private String loginName;
        private String name;

        public ShiroUser(Long id, String loginName, String name) {
            this.id = id;
            this.loginName = loginName;
            this.name = name;
        }

        public Long getId() {
            return id;
        }

        public String getLoginName() {
            return loginName;
        }

        public String getName() {
            return name;
        }

        /**
         * <shiro:principal/>输出.
         */
        @Override
        public String toString() {
            logger.debug("ShiroUser{" +
                    "id=" + id +
                    ", loginName='" + loginName + '\'' +
                    ", name='" + name + '\'' +
                    '}');
            return name;
        }

        /**
         * 重载hashCode,只计算loginName;
         */
        @Override
        public int hashCode() {
            return loginName.hashCode();
        }

        /**
         * 重载equals,只计算loginName;
         */
        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            ShiroUser other = (ShiroUser) obj;
            if (loginName == null) {
                if (other.loginName != null) {
                    return false;
                }
            } else if (!loginName.equals(other.loginName)) {
                return false;
            }
            return true;
        }
    }
}
